﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Slick.MapEditor;
using Clandestine;
using Clandestine.Entities;
using System.Threading;

namespace Slick
{
    public partial class EntityPropertiesControl : UserControl
    {
        public Map Map;

        public EntityPropertiesControl()
        {
            InitializeComponent();
        }

        public void Initialise(Map map)
        {
            // Setup stuff & Events
            this.Map = map;
            Map.Entities.OnEntityAdded += new EntityAdded(Entities_OnEntityAdded);
            Map.Entities.OnEntityListRefreshed += new EntityListRefreshed(Entities_OnEntityListRefreshed);
            Map.Entities.OnEntitySelected += new EntitySelected(Entities_OnEntitySelected);
        }


        /// <summary>
        /// Called when the selected entity in the combo box changes - i.e. selected entity changes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboEntities_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Pass to EntityManager to make selection and raise appropriate event for us to handle.
            Map.Entities.SelectEntity((Entity)comboEntities.SelectedItem);
        }

        /// <summary>
        /// Called when the user has selected an entity (by clicking or using the combo box)
        /// </summary>
        /// <param name="e"></param>
        void Entities_OnEntitySelected(Entity e)
        {
            // Must be in GUI thread
            this.Invoke(new ThreadStart(delegate()
            {
                EntityProperties.SelectedObject = e;
                comboEntities.SelectedItem = e; // just incase it wasn't a selection through that which raised this!
            }));
        }

        /// <summary>
        /// Adds an entity instance to the combo box
        /// </summary>
        /// <param name="e"></param>
        public void AddEntity(Entity e)
        {
            comboEntities.Items.Add(e);
        }

        /// <summary>
        /// Raised when the list of entities on the map is refreshed i.e. one or more deleted!
        /// </summary>
        void Entities_OnEntityListRefreshed()
        {
            // Need to copy list of entities for local use
            List<Entity> ec = new List<Entity>();
            lock (Map.Entities)
                foreach (Entity e in Map.Entities)
                    ec.Add(e);

            // Must be called in GUI thread!
            this.Invoke(new ThreadStart(delegate()
            {
                comboEntities.Items.Clear();

                foreach (Entity e in ec)
                    AddEntity(e);

                // Reselect old entity selection.
                lock (Map.Entities.SelectedEntityBlob)
                    if (Map.Entities.SelectedEntity != null)
                        comboEntities.SelectedItem = Map.Entities.SelectedEntity;
            }));
        }

        /// <summary>
        /// Called when user adds an entity to the map. We must update our combo box of instances
        /// </summary>
        /// <param name="e">The entity added.</param>
        void Entities_OnEntityAdded(Clandestine.Entities.Entity e)
        {
            // Must add in another thread!
            this.Invoke(new ThreadStart(delegate()
            {
                AddEntity(e);
            }));
        }

        private void EntityProperties_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            // If trigger is changed, have to update size and layer of the sprite!
            if (EntityProperties.SelectedObject is Clandestine.Entities.Trigger)
            {
                Trigger t = ((Trigger)EntityProperties.SelectedObject);
                Sprite spr = Map.Entities.GetTriggerSprite(t);

                spr.ScaleX = t.Size.Width;
                spr.ScaleY = t.Size.Height;
                spr.Position = t.Position;
                spr.Layer = t.Layer + 0.01f;
            }
        }

    }
}
